const fs = require('fs');
const path = require('path');
const axios = require('axios');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');

// 配置命令行参数
const argv = yargs(hideBin(process.argv))
    .options({
        'host': {
            alias: 'h',
            description: '服务器主机地址',
            default: '127.0.0.1',
            type: 'string',
            demandOption: false
        },
        'port': {
            alias: 'p',
            description: '服务器端口',
            default: 8080,
            type: 'number',
            demandOption: false
        },
        'user': {
            alias: 'u',
            description: '用户名',
            default: 'zs',
            type: 'string',
            demandOption: false
        },
        'pwd': {
            alias: 'w',
            description: '密码',
            default: 'ddd',
            type: 'string',
            demandOption: false
        }
    })
    .usage('用法: $0 [选项]')
    .example('$0 --host=localhost --port=8080 --user=zs --pwd=ddd', '使用指定参数连接服务器')
    .example('$0 -h localhost -p 8080 -u zs -w ddd', '使用简写形式连接服务器')
    .describe('help', '显示帮助信息')
    .describe('host', '服务器主机地址')
    .describe('port', '服务器端口')
    .describe('user', '用户名')
    .describe('pwd', '密码')
    .epilog('注意：所有参数都有默认值，可以单独使用 --参数名 查看当前值')
    .strict()
    .check((argv) => {
        // 如果只提供了参数名而没有值，显示当前值
        if (process.argv.includes('--host') && process.argv[process.argv.indexOf('--host') + 1] === undefined) {
            console.log('当前主机地址:', argv.host);
            process.exit(0);
        }
        if (process.argv.includes('--port') && process.argv[process.argv.indexOf('--port') + 1] === undefined) {
            console.log('当前端口:', argv.port);
            process.exit(0);
        }
        if (process.argv.includes('--user') && process.argv[process.argv.indexOf('--user') + 1] === undefined) {
            console.log('当前用户名:', argv.user);
            process.exit(0);
        }
        if (process.argv.includes('--pwd') && process.argv[process.argv.indexOf('--pwd') + 1] === undefined) {
            console.log('当前密码:', argv.pwd);
            process.exit(0);
        }
        return true;
    })
    .argv;

const serverUrl = `http://${argv.host}:${argv.port}`;
const axiosInstance = axios.create({
    baseURL: serverUrl,
    headers: {
        'Authorization': `Basic ${Buffer.from(`${argv.user}:${argv.pwd}`).toString('base64')}`
    }
});

// 错误处理函数
const handleError = (error) => {
    if (error.response) {
        if (error.response.status === 401) {
            console.error('认证失败: 用户名或密码错误');
        } else {
            console.error('服务器错误:', error.response.data);
            if (error.response.data.code) {
                console.error('错误代码:', error.response.data.code);
            }
            if (error.response.data.error) {
                console.error('错误信息:', error.response.data.error);
            }
        }
    } else if (error.request) {
        console.error('请求失败: 无法连接到服务器');
    } else {
        console.error('错误:', error.message);
    }
};

// 处理命令
const handleCommand = async (command) => {
    const [cmd, ...args] = command.split(' ');

    switch (cmd) {
        case 'upload':
            if (args.length !== 1) {
                console.log('用法: upload <文件路径>');
                return;
            }
            const filePath = path.resolve(args[0]);
            
            try {
                if (!fs.existsSync(filePath)) {
                    console.error('文件不存在:', filePath);
                    return;
                }

                const fileData = fs.readFileSync(filePath);
                const filename = path.basename(filePath);
                
                const requestBody = {
                    filename: filename,
                    data: fileData.toString('base64')
                };
                
                console.log(`正在上传文件: ${filename} (${fileData.length} 字节)`);
                const response = await axiosInstance.post('/upload', requestBody);
                console.log('服务器响应:', response.data);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'download':
            if (args.length !== 1) {
                console.log('用法: download <文件名>');
                return;
            }
            try {
                const filename = args[0];
                const response = await axiosInstance.get(`/download/${filename}`);
                const buffer = Buffer.from(response.data.data, 'base64');
                fs.writeFileSync(filename, buffer);
                console.log(`文件下载成功: ${filename}`);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'delete':
            if (args.length !== 1) {
                console.log('用法: delete <文件名>');
                return;
            }
            try {
                const filename = args[0];
                const response = await axiosInstance.delete(`/delete/${filename}`);
                console.log('服务器响应:', response.data);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'rename':
            if (args.length !== 2) {
                console.log('用法: rename <旧文件名> <新文件名>');
                return;
            }
            try {
                const [oldName, newName] = args;
                const response = await axiosInstance.post('/rename', {
                    oldName,
                    newName
                });
                console.log('服务器响应:', response.data);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'mkdir':
            if (args.length !== 1) {
                console.log('用法: mkdir <目录名>');
                return;
            }
            try {
                const dirname = args[0];
                const response = await axiosInstance.post('/mkdir', { dirname });
                console.log('服务器响应:', response.data);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'list':
            try {
                const response = await axiosInstance.get('/list');
                console.log('目录内容:');
                response.data.items.forEach(item => {
                    console.log(`${item.isDirectory ? 'd' : '-'} ${item.name}${item.isDirectory ? '/' : ''}`);
                });
            } catch (error) {
                handleError(error);
            }
            break;

            case 'lcd':
    if (args.length !== 1) {
        console.log('用法: lcd <目录绝对路径>');
        return;
    }
    try {
        const dirPath = args[0];
        
        // 检查是否是绝对路径
        if (!path.isAbsolute(dirPath)) {
            console.error('错误: 必须使用绝对路径');
            return;
        }

        // 规范化路径（处理正斜杠和反斜杠）
        const normalizedPath = path.normalize(dirPath);

        // 检查目录是否存在，如果不存在则创建
        if (!fs.existsSync(normalizedPath)) {
            try {
                fs.mkdirSync(normalizedPath, { recursive: true });
                console.log(`目录不存在，已创建: ${normalizedPath}`);
            } catch (mkdirErr) {
                console.error('创建目录失败:', mkdirErr.message);
                return;
            }
        }

        // 切换目录
        process.chdir(normalizedPath);
        console.log(`本地目录已切换到: ${process.cwd()}`);
    } catch (error) {
        console.error('切换本地目录失败:', error.message);
    }
    break;

        case 'lpwd':
            console.log('当前本地目录:', process.cwd());
            break;

        case 'rcd':
            if (args.length !== 1) {
                console.log('用法: rcd <目录路径>');
                return;
            }
            try {
                const dirPath = args[0];
                const response = await axiosInstance.post('/cd', { path: dirPath });
                console.log('服务器响应:', response.data);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'rpwd':
            try {
                const response = await axiosInstance.get('/pwd');
                console.log('当前服务器目录:', response.data.path);
            } catch (error) {
                handleError(error);
            }
            break;

        case 'help':
            console.log('可用命令：');
            console.log('  upload <文件>      - 上传文件到服务器');
            console.log('  download <文件>    - 下载服务器文件');
            console.log('  delete <文件>      - 删除文件');
            console.log('  rename <旧> <新>   - 重命名文件');
            console.log('  mkdir <目录>       - 创建目录');
            console.log('  list              - 显示目录内容');
            console.log('  lcd <目录>        - 切换本地目录');
            console.log('  lpwd              - 显示本地目录');
            console.log('  rcd <目录>        - 切换服务器目录');
            console.log('  rpwd              - 显示服务器目录');
            console.log('  help              - 显示此帮助');
            console.log('  exit              - 退出程序');
            break;

        case 'exit':
            console.log('再见!');
            process.exit(0);
            break;

        default:
            console.log('未知命令。输入 help 查看可用命令。');
    }
};


// 显示初始连接信息
console.log(`连接到服务器: ${serverUrl}`);
console.log(`用户: ${argv.user}`);
console.log('输入 help 查看可用命令\n');

// 主程序循环
const main = () => {
    process.stdin.on('data', (data) => {
        const command = data.toString().trim();
        handleCommand(command);
    });
};

main();